<?php

/**
 * 属性（值）同步类
 *
 * @author    Y.N
 * @copyright    www.360hqb.com
 * @access       public
 * @update	2011/3/25
 */
class Sync_Props
{
    /**
	 * 获取淘宝属性（值）数据
	 *
	 * @param	int $cid
	 * @access	public
	 * @return	object
	 * @update	2011/3/21
	*/
	public static function get_taobao_props($cid)
	{
	    assert("is_numeric('$cid')"); // 判断是否数字类型
        $url = "http://open.taobao.com/api_tool/props/ajaxProps.php?action=props&cid=$cid&restBool=false";
        $i = 1;
        while (true)
		{
			$data = @file_get_contents($url);

			if ( ! empty($data) || $i>=8) {
                break;
            } else {
                CLI::output ('.');
                sleep($i++);
            }
        }
		unset($i, $url);

		// 格式化
        $data = preg_replace('/[\s\x{3000}]+/u', ' ', preg_split('/\s*\n\s*/', $data));

        // 反编码
        $std = new stdClass();
		if (isset($data[0]))
		{
			$props = json_decode(substr(str_replace('var props=', '', $data[0]), 0, -1));
			$std->props = isset($props->itemprops_get_response->item_props->item_prop) ?
				$props->itemprops_get_response->item_props->item_prop :
				array();
		}else {
		    $std->props = array();
		}
		if (isset($data[1]))
		{
		    $propvalues = json_decode(substr(str_replace('var propvalues=', '', $data[1]), 0, -1));
			$std->propvalues = isset($propvalues->itempropvalues_get_response->prop_values->prop_value) ?
				$propvalues->itempropvalues_get_response->prop_values->prop_value :
				array();
		}else {
		    $std->propvalues = array();
		}

		unset($data);
        return $std;

	} // end func


	/**
	 * 同步属性
	 *
	 * @param	object $props,
	 * @param	int $cid
	 * @access	public
	 * @return	void
	 * @update	2011/3/22
	*/
	public static function save_props($props, $cid)
	{
		$number = 0;

		// 循环属性
	    foreach ($props as $k => $prop)
	    {
			// 过滤淘宝的非正常使用数据
			if (strtolower($prop->status) != 'normal' or empty($prop->name))
			{
				continue;
			}
			$data = array(
				'pid' => $prop->pid,
				'parent_pid' => $prop->parent_pid,
				'name' => $prop->name,
			);

			/* 过滤已经存在的属性，数据是否已存在 */
			$old = DB::select(DB::expr('COUNT(*)'))
				->from('item_props')
				->where('pid', '=',$prop->pid)
				->fetch_one();

			CLI::output(".");

			// 匹配名称
			$row = DB::select()
				->from('item_props')
				->where('name', '=', $prop->name)
				->where('parent_pid', '=', $prop->parent_pid)
				->where('is_new','=',1)
				->fetch_row();

			// 匹配名称成功，则为后台自动录入数据
			if ($row)
			{
				// 更新匹配的pid

				$cat_props = DB::select('*')
					->from('item_cat_props')
					->where('pid', '=', $row['pid'])
					->fetch_all();
				foreach ($cat_props as $cat_p)
				{
					$count = DB::select(DB::expr('count(*)'))
						->from('item_cat_props')
						->where('cid', '=', $cat_p['cid'])
						->where('pid', '=', $prop->pid)
						->fetch_one();
					if ($count)
					{
						DB::delete('item_cat_props')
							->where('cid', '=', $cat_p['cid'])
							->where('pid', '=', $row['pid'])
							->execute();
					} else {
						DB::update('item_cat_props')
							->set(array('pid' => $prop->pid))
							->where('pid', '=', $row['pid'])
							->where('cid', '=', $cat_p['cid'])
							->execute();
					}
				}

				CLI::output("更新后台录入属性：".$row['name']." 成功\n");
				/** 查找是否已录入该属性的产品 **/
				$select = DB::select('product_id','props','binds')
					->from('products')
					->where_open()
					->where('props', 'REGEXP', ';'.$row['pid'].':|^'.$row['pid'].':')
					->or_where('binds', 'REGEXP', ';'.$row['pid'].':|^'.$row['pid'].':')
					->where_close()
					->and_where('status', '=', 3)
					->and_where('product_id', '>=', 300000000);

				$iterator = new Db_Iterator($select, 'default', 20);
				while ($iterator->valid())
				{
					foreach ($iterator->current() as $p)
					{
						$set = array(
							'props' => self::props_replace($row['pid'], $prop->pid, $p['props']),
							'binds' =>  self::props_replace($row['pid'], $prop->pid, $p['binds']),
						);
						DB::update('products')->set($set)->where('product_id', '=', $p['product_id'])->execute();

						CLI::output("更新产品ID：".$p['product_id']." 成功\n");
						// 更新商品
						$select = DB::select('goods_id','props')
							->from('goods')
							->where('product_id', '=', $p['product_id']);
						$iterator_goods = new Db_Iterator($select, 'default', 20);
						// 批量替换
						self::batch_replace($iterator_goods, $row['pid'], $prop->pid);
						unset($iterator_goods);
					}
					$iterator->next();
				}

				/** 查找是否已录入该属性的商品 **/
				$select = DB::select('goods_id', 'props')
					->from('goods')
					->where('props', 'REGEXP', ';'.$row['pid'].':|^'.$row['pid'].':')
					->where('deleted', '=', 0)
					->where('goods_id', '>', 80000);
				// 写入迭代器
				$iterator = new Db_Iterator($select, 'default', 20);
				// 进行批量替换
				self::batch_replace($iterator, $row['pid'], $prop->pid);
				unset($iterator);

				// 所有替换完毕，删除后台手动录入的数据
				DB::delete('item_props')->where('pid', '=', $row['pid'])->execute();

				// 写入日志
				new Sync_Exception('<!-----del----!>匹配成功！删除后台录入属性：（'.$row['name'].'['.$row['pid'].']）', 109, __FUNCTION__, __CLASS__);
				unset($iterator, $select, $set);
			}
			unset($row);

			if ( ! $old)
			{
				// 写入属性表
				DB::replace('item_props', $data)->execute();

				CLI::output("写入新属性：".$data['name']." 成功\n");


				// 写入日志
				new Sync_Exception('子叶类目：('.$cid.')下新增属性 ('.$prop->name.'['.$prop->pid.'])', 148, __FUNCTION__, __CLASS__);
				$number ++;
			}
			unset($old);
			$count = DB::select(DB::expr('count(*)'))
				->from('item_cat_props')
				->where('cid', '=', $cid)
				->where('pid', '=', $prop->pid)
				->where('parent_vid', '=', $prop->parent_vid)
				->fetch_one();
			if ( ! $count)
			{
				/** 更新属性类目表 **/
				$new_data = array(
					'pid' => $prop->pid,
					'cid' => $cid,
					'parent_vid' => $prop->parent_vid,
					'name_alias' => $prop->name,
					'is_color_prop' => $prop->is_color_prop ? 1 : 0,
					'is_enum_prop' => $prop->is_enum_prop ? 1 : 0,
					'is_input_prop' => $prop->is_input_prop ? 1 : 0,
					'is_item_prop' => $prop->is_item_prop ? 1 : 0,
					'is_key_prop' => $prop->is_key_prop ? 1 : 0,
					'is_sale_prop' => $prop->is_sale_prop ? 1 : 0,
					'multi' => $prop->multi ? 1 : 0,
					'must' => $prop->must ? 1 : 0,
					'child_template' => isset($prop->child_template) ? $prop->child_template : '',
				);
				DB::replace('item_cat_props', $new_data)->execute();
				CLI::output("类目ID：".$cid." 绑定属性成功\n");
				unset($new_data);
			}
	    }
		if ($number)
		{
			// 写入日志
			new Sync_Exception('======>子叶类目：('.$cid.')下共新增属性 ('.$number.') 条数据', 176, __FUNCTION__, __CLASS__);
		}
		unset($props, $data, $number, $cid);

	} // end func

	/**
	 * 同步属性 (值)
	 *
	 * @param	object $prop_values,
	 * @param	int $cid
	 * @access	public
	 * @return	void
	 * @update	2011/3/22
	*/
	public static function save_prop_values($prop_values,$cid)
	{
		$number = 0;

		foreach ($prop_values as $k => $val)
	    {
			// 过滤非正常使用数据
			if (strtolower($val->status) != 'normal' or empty($val->name))
			{
				continue;
            }

			$data = array(
				'vid' => $val->vid,
				'name' => $val->name,
			);
			/* 过滤已经存在的属性（值） */
			$old = DB::select(DB::expr('COUNT(*)'))
				->from('item_prop_values')
				->where('vid', '=', $val->vid)
				->fetch_one();

			CLI::output(".");

			// 匹配名称
			$row = DB::select()
				->from('item_prop_values')
				->where('name', '=', $val->name)
				->where('is_new','=',1)
				->fetch_row();

			// 匹配名称成功，则为后台自动录入数据
			if ($row)
			{
				$cat_values = DB::select('*')
					->from('item_cat_values')
					->where('vid', '=', $row['vid'])
					->fetch_all();
				foreach ($cat_values as $cat_v)
				{
					$count = DB::select(DB::expr('count(*)'))
						->from('item_cat_values')
						->where('cid', '=', $cat_v['cid'])
						->where('pid', '=', $cat_v['pid'])
						->where('vid', '=', $val->vid)
						->fetch_one();
					if ($count)
					{
						DB::delete('item_cat_values')
							->where('cid', '=', $cat_v['cid'])
							->where('pid', '=', $cat_v['pid'])
							->where('vid', '=', $row['vid'])
							->execute();
					} else {
						DB::update('item_cat_values')
							->set(array('vid' => $val->vid))
							->where('cid', '=', $cat_v['cid'])
							->where('pid', '=', $cat_v['pid'])
							->where('vid', '=', $row['vid'])
							->execute();
					}
				}

				CLI::output("更新后台录入属性值：".$row['name']." 成功\n");
				/** 更新产品 **/
				$vid_len = strlen($row['vid']);

				$select = DB::select('product_id','props','binds')
					->from('products')
					->where_open()
					->where('props', 'REGEXP', ':'.$row['vid'].';|:'.$row['vid'].'$')
					->or_where('binds', 'REGEXP', ':'.$row['vid'].';|:'.$row['vid'].'$')
					->where_close()
					->and_where('status', '=', 3)
					->and_where('product_id', '>=', 300000000);

				$iterator = new Db_Iterator($select, 'default', 20);
				while ($iterator->valid())
				{
					foreach ($iterator->current() as $p)
					{
						$set = array(
							'props' => self::props_replace($row['vid'], $val->vid, $p['props'], '2'),
							'binds' =>  self::props_replace($row['vid'], $val->vid, $p['binds'], '2'),
						);
						DB::update('products')->set($set)->where('product_id', '=', $p['product_id'])->execute();
						CLI::output("更新产品ID：".$p['product_id']." 成功\n");

						// 更新商品
						$select = DB::select('goods_id','props')
							->from('goods')
							->where('product_id', '=', $p['product_id']);

						$iterator_goods = new Db_Iterator($select, 'default', 20);
						// 批量替换
						self::batch_replace($iterator_goods, $row['vid'], $val->vid, '2');
						unset($iterator_goods);
					}
					$iterator->next();
				}

				/** 更新商品 **/
				$select = DB::select('goods_id','props')
					->from('goods')
					->where('props', 'REGEXP', ':'.$row['vid'].';|:'.$row['vid'].'$')
					->where('deleted', '=', 0)
					->where('goods_id', '>', 80000);

				$iterator = new Db_Iterator($select, 'default', 20);
				// 批量替换
				self::batch_replace($iterator, $row['vid'], $val->vid, '2');
				unset($iterator);

				DB::delete('item_prop_values')->where('vid', '=', $row['vid'])->execute();
				// 写入日志
				new Sync_Exception('<!-----del----!>匹配成功！删除后台录入属性（值）：（'.$row['name'].'['.$row['vid'].']）', 232, __FUNCTION__, __CLASS__);

				unset($iterator, $select, $set);
			}
			unset($row);

			/** 不存在则录入 **/
			if ( ! $old)
			{
				DB::replace('item_prop_values', $data)->execute();

				CLI::output("写入新属性值：".$data['name']." 成功\n");

				// 写入日志
				new Sync_Exception('子叶类目：('.$cid.')下新增属性 (值) ('.$val->name.'['.$val->vid.'])', 271, __FUNCTION__, __CLASS__);
				$number++;
			}
			unset($old);
			$count = DB::select(DB::expr('count(*)'))
				->from('item_cat_values')
				->where('cid', '=', $cid)
				->where('pid', '=', $val->pid)
				->where('vid', '=', $val->vid)
				->fetch_one();
			if ( ! $count)
			{
				/** 更新属性 (值) 类目表 **/
				$new_data = array(
					'cid' => $cid,
					'vid' => $val->vid,
					'pid' => $val->pid,
					'name_alias' => isset($val->name_alias) ? $val->name_alias : '',
				);
				DB::replace('item_cat_values', $new_data)->execute();
				CLI::output("类目ID：".$cid." 绑定属性值成功\n");
				unset($new_data);
			}
	    }
		if ($number)
		{
		    // 写入日志
			new Sync_Exception('======>子叶类目：('.$cid.')下共新增属性 (值) ('.$number.') 条数据', 291, __FUNCTION__, __CLASS__);
		}
		unset($prop_values, $number, $cid, $count);

	} // end func

	/**
	 * 完全字符替换
	 *
	 * @param	string $string 被替换的字符串,
	 * @param	string $search 需要替换的字符串,
	 * @param	string $replace 替换为的字符串
	 * @param	string $t(1：更新属性id , 2：更新属性值id)
	 * @access	public
	 * @return	array
	 * @update	2011/3/26
	*/
	public static function props_replace($search, $replace, $string, $t = '1')
	{
		if ( empty($string))
		{
		    return false;
		}
		// 拆分字符串
		$explode = explode(';', $string);

		$new = array();
		foreach ($explode as $e)
		{
			$props = explode(':', $e);
			if ($t == '1')
			{
			    if (current($props) == $search)
			    {
			        $props[0] = $replace;
			    }
			}else {
			    if (end($props) == $search)
			    {
			        $props[1] = $replace;
			    }
			}
			// 重新组合
			$props_str = implode(':', $props);
			$new[] = $props_str;
		}
		return implode(';', $new);
		unset($new);

	} // end func


	/**
	 * 批量替换商品
	 *
	 * @param	array $goods,
	 * @param	string $search 需要替换的字符,
	 * @param	string $replace 替换后的字符
	 * @param	string $t(1：更新属性id , 2：更新属性值id)
	 * @access	public
	 * @return	void
	 * @update	2011/3/26
	*/
	public static function batch_replace($iterator, $search, $replace, $t = '1')
	{
		while ($iterator->valid())
		{
			// 循环每一个商品
			foreach ($iterator->current() as $g)
			{
				// 替换
				$set = array(
					'props' => self::props_replace($search, $replace, $g['props'], $t)
				);
				DB::update('goods')->set($set)->where('goods_id', '=', $g['goods_id'])->execute();

				CLI::output("更新商品ID：".$g['goods_id']." 成功\n");
				// 删除商品属性表
				DB::delete('goods_props')->where('goods_id', '=', $g['goods_id'])->execute();

				// 重新写入商品属性表
				$props = explode(';', $set['props']);
				foreach ($props as $p)
				{
					if ($p)
					{
						$row = array(
							'goods_id' => $g['goods_id'],
							'props' => $p,
						);
						DB::replace('goods_props',$row)->execute();
						unset($row);
					}
				}
				unset($g, $props, $set);
			}
			$iterator->next();
		}
	} // end func

} // end class


